package com.xbongbong.paas.service.impl;

import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.ConfigConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.service.SmsFeeService;
import com.xbongbong.paas.service.alipay.SmsAlipayService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.CommentUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.TwoDimensionCodeEncoder;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.sms.model.SmsConfigModel;
import com.xbongbong.pro.sms.pojo.SmsFeeChargePojo;
import com.xbongbong.pro.sms.pojo.SmsFeeLogPojo;
import com.xbongbong.pro.sms.pojo.SmsFeePojo;
import com.xbongbong.pro.sms.pojo.dto.SmsFeeChargeDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsFeeInfoDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsFeeLogDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsFeePayStatusDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsFeeQrCodeDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsPayInfoDTO;
import com.xbongbong.pro.sms.pojo.vo.SmsFeeChargeVO;
import com.xbongbong.pro.sms.pojo.vo.SmsFeeInfoVO;
import com.xbongbong.pro.sms.pojo.vo.SmsFeeLogVO;
import com.xbongbong.pro.sms.pojo.vo.SmsFeePayStatusVO;
import com.xbongbong.pro.sms.pojo.vo.SmsFeeQrCodeVO;
import com.xbongbong.pro.sms.pojo.vo.SmsPayInfoVO;
import com.xbongbong.saas.constant.SmsSetConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.SmsConfigEntity;
import com.xbongbong.saas.enums.FeePayStatusEnum;
import com.xbongbong.saas.enums.FeePayTypeEnum;
import com.xbongbong.saas.enums.FeeStatusEnum;
import com.xbongbong.sys.domain.entity.CompanyEntity;
import com.xbongbong.sys.domain.entity.FeeEntity;
import com.xbongbong.sys.domain.entity.FeeLogEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.CompanyModel;
import com.xbongbong.sys.model.FeeLogModel;
import com.xbongbong.sys.model.FeeModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.xbongbong.paas.toolbox.util.DateUtil.SDFYMDHM;

/**
 * @description: 短信套餐
 * @Author: hongxiao
 * @date: 2019-01-13 17:02
 */
@Service("SmsFeeService")
public class SmsFeeServiceImpl implements SmsFeeService {

    private static final Logger LOG = LoggerFactory.getLogger(SmsSetServiceImpl.class);

    @Resource
    private SmsConfigModel smsConfigModel;
    @Resource
    private FeeModel feeModel;
    @Resource
    private UserModel userModel;
    @Resource
    private FeeLogModel feeLogModel;
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private SmsAlipayService smsAlipayService;

    @Override
    public SmsFeeInfoVO getInfo(SmsFeeInfoDTO smsFeeDetailDTO) throws XbbException {
        SmsFeeInfoVO smsFeeInfoVO = new SmsFeeInfoVO();
        try {
            String corpid = smsFeeDetailDTO.getCorpid();

            Integer smsCounts = 0;
            CompanyEntity companyEntity = companyModel.getByKey(corpid);
            if(companyEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100011);
            }
            String corpName = companyEntity.getCorpName();
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("del", DelEnum.NORMAL.getDel());
            List<SmsConfigEntity> configList = smsConfigModel.findEntitys(param);
            if (configList != null && configList.size() > 0) {
                SmsConfigEntity confEntity = configList.get(0);
                smsCounts = confEntity.getSmsCount();
            }

            List<SmsFeePojo> feePoJoList = new ArrayList<>();
            //获取短信套餐
            param.clear();
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("type", PackageTypeEnum.SMS.getType());
            param.put("status", FeeStatusEnum.PAY_USER_VISIBLE.getCode());
            param.put("orderByStr", "real_price asc");
            List<FeeEntity> feeList = feeModel.findEntitys(param);
            if (feeList != null && feeList.size() > 0) {
                for (FeeEntity entity : feeList) {
                    String priceName = String.format(I18nMessageUtil.getMessage(StringConstant.FEE_PRICE_NAME), entity.getPrice());
                    String realPriceName = String.format(I18nMessageUtil.getMessage(StringConstant.FEE_REAL_PRICE_NAME), entity.getRealPrice());
                    SmsFeePojo smsFeePojo = new SmsFeePojo();
                    smsFeePojo.setFeeId(entity.getId());
                    smsFeePojo.setPriceName(priceName);
                    smsFeePojo.setRealPriceName(realPriceName);
                    smsFeePojo.setContent(entity.getContent());
                    feePoJoList.add(smsFeePojo);
                }
            }

            smsFeeInfoVO.setCorpName(corpName);
            smsFeeInfoVO.setSmsCounts(smsCounts);
            smsFeeInfoVO.setFeeList(feePoJoList);

        } catch (Exception e) {
            LOG.error("获取短信套餐信息失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return smsFeeInfoVO;
    }

    @Override
    public SmsFeeChargeVO charge(SmsFeeChargeDTO smsFeeChargeDTO) throws XbbException {
        SmsFeeChargeVO smsFeeChargeVO = new SmsFeeChargeVO();

        String corpid = smsFeeChargeDTO.getCorpid();
        Long feeId = smsFeeChargeDTO.getFeeId();
        Integer payType = smsFeeChargeDTO.getPayType();

        try {

            FeeEntity feeEntity = feeModel.getByKey(feeId);
            if (feeEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, SmsSetConstant.SMS_PACKAGE_NOT_EXIST);
            }

            FeePayTypeEnum payTypeEnum = null;
            if (payType != null) {
                payTypeEnum = FeePayTypeEnum.getByCode(payType);
            }
            payType = null != payTypeEnum ? payType : FeePayTypeEnum.OFFLINE_PAY.getCode();

            float realPrice = feeEntity.getRealPrice();
            float price = feeEntity.getPrice();

            String opUserName = smsFeeChargeDTO.getLoginUserName();
            CompanyEntity companyEntity = companyModel.getByKey(corpid);
            if(companyEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100011);
            }
            String corpName = companyEntity.getCorpName();

            Long now = DateUtil.getLong();
            //随机字符串,Util中方法包含特殊字符串
            char[] charList = {'0', '1', '2', '3', '4', '5', '6', '7',
                    '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
                    'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
                    'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
                    'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
                    'Y', 'Z'};
            StringBuffer randomString = new StringBuffer();
            randomString.append(charList[(int) (Math.random() * 62)]);
            randomString.append(charList[(int) (Math.random() * 62)]);
            randomString.append(charList[(int) (Math.random() * 62)]);
            randomString.append(charList[(int) (Math.random() * 62)]);
            /*
             * 保证不能重复！支付回调时，根据outTradeNo处理
             */
            String outTradeNo = now.toString() + randomString + (int) price;
            // TODO 服务器地址写死
            String serverUrl = "http://proadmin.xbongbong.com/";


            FeeLogEntity entity = new FeeLogEntity();
            entity.setCorpid(corpid);
            entity.setCorpName(corpName);
            entity.setFeeType(PackageTypeEnum.SMS.getType());
            entity.setFeeId(feeId);
            entity.setFeeName(feeEntity.getName());
            entity.setRealPrice(realPrice);
            entity.setBuyNum(1);
            entity.setContent(feeEntity.getContent());
            entity.setFee(realPrice);
            entity.setIsPay(FeePayStatusEnum.WAIT_PAY.getCode());
            entity.setPayType(payType);
            entity.setOpUserName(opUserName);
            entity.setSumValue(feeEntity.getPrimaryNum());
            /*
             * 支付宝外部交易流水号,线下支付也使用这个
             */
            entity.setOrderId(outTradeNo);

            feeLogModel.insert(entity);

            Long feeLogId = entity.getId();
            SmsFeeChargePojo chargePoJo = new SmsFeeChargePojo();
            chargePoJo.setFeeId(feeId);
            chargePoJo.setTotalFee(feeEntity.getRealPrice());
            chargePoJo.setSmsNum(feeEntity.getPrimaryNum());
            chargePoJo.setFeeDescription(feeEntity.getContent());

            smsFeeChargeVO.setFeeLogId(feeLogId);
            smsFeeChargeVO.setOutTradeNo(outTradeNo);
            smsFeeChargeVO.setServerUrl(serverUrl);
            smsFeeChargeVO.setFee(chargePoJo);

        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("支付短信套餐失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return smsFeeChargeVO;
    }

    @Override
    public SmsFeePayStatusVO checkPayStatus(SmsFeePayStatusDTO smsFeePayStatusDTO) throws XbbException {
        SmsFeePayStatusVO smsFeePayStatusVO = new SmsFeePayStatusVO();
        try {
            String corpid = smsFeePayStatusDTO.getCorpid();
            Long feeLogId = smsFeePayStatusDTO.getFeeLogId();
            if (null == feeLogId) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, SystemErrorCodeEnum.API_ERROR_100002.getMsg());
            }
            FeeLogEntity entity = feeLogModel.getByKey(feeLogId, corpid);
            if (entity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, SmsSetConstant.SMS_PAYMENT_RECORD_NOT_EXIST);
            }
            smsFeePayStatusVO.setPayStatus(entity.getIsPay());
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("获取短信套餐支付状态失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return smsFeePayStatusVO;
    }

    /**
     * TODO 需改写，原逻辑已有问题
     */
    @Override
    public SmsFeeQrCodeVO getQRCode(SmsFeeQrCodeDTO smsFeeQrCodeDTO) throws XbbException {
        SmsFeeQrCodeVO smsFeeQrCodeVO = new SmsFeeQrCodeVO();

        // 此处需要对参数做一些校验，毕竟是付钱啊，防止用户手动修改
        String corpid = smsFeeQrCodeDTO.getCorpid();
        Long feeLogId = smsFeeQrCodeDTO.getFeeLogId();
        FeeLogEntity feeLogEntity = feeLogModel.getByKey(feeLogId, corpid);
        if(feeLogEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, SmsSetConstant.SMS_PURCHASE_HISTORY_NOT_EXIST);
        }
        try {
            // TODO 是否可用旧的页面跳转支付
            // pro微应用appId，对应原来的DefaultConfig.getValue("dingXbbAppId")
            String appId = ProBaseConfig.getAppId();
            // 钉钉微应用端域名，对应原来的DefaultConfig.getValue("appUrl")
            String appUrl = proBaseConfig.getPushFrontUrl();
//            String appUrl = "http://192.168.10.137:8082/";
            // TODO 短信支付宝支付的前端页面 feeLogEntity.getRealPrice()
            String content = appUrl +  "index.html?corpid=" + corpid + "&appid=" + appId + "&dd_nav_bgcolor=ffff943e" +
                    "#/pay/index?corpid=" + corpid + "&appid=" + appId + "&totalFee=" + feeLogEntity.getRealPrice()
                    + "&outTradeNo=" + feeLogEntity.getOrderId() + "&feeId=" + feeLogEntity.getFeeId()
                    + "&feeDescription=" + feeLogEntity.getContent()
                    + "&feeLogId=" + feeLogId + "&smsNum=" + feeLogEntity.getSumValue();
            BufferedImage qrCode = TwoDimensionCodeEncoder.get2DCode(content, 180, 180);
            byte[] qrCodeBytes = TwoDimensionCodeEncoder.BufferedImage2Bytes(qrCode);
            /*
            base64 要求每76个字符加回车换行，我们返回前端的图片base64不能带回车换行，
            使用apache codec 的 Base64工具类不会出现回车换行，其他工具类可能出现回车换行
             */
            String qrCodeBase64 = Base64.encodeBase64String(qrCodeBytes);

            // jpg/jpeg 图片转化为base64为字符串后的前缀 + 图片base64码
            smsFeeQrCodeVO.setQrCode(ConfigConstant.JPEG_IMG_BASE64_HEADER + qrCodeBase64);

        } catch (Exception e) {
            LOG.error("获取短信套餐二维码失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return smsFeeQrCodeVO;
    }

    @Override
    public SmsFeeLogVO logList(SmsFeeLogDTO smsFeeLogDTO) throws XbbException {
        SmsFeeLogVO smsFeeLogVO = new SmsFeeLogVO();

        String userId = smsFeeLogDTO.getUserId();
        String corpid = smsFeeLogDTO.getCorpid();

        try {

            UserEntity userEntity = userModel.getByKey(userId, corpid);
            if (userEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004, SystemErrorCodeEnum.API_ERROR_100004.getMsg());
            }
            //查询条件
            String orderIdLike = smsFeeLogDTO.getOutTradeNo();
            List<String> timeSpan = smsFeeLogDTO.getTimeSpan();
            String opUserNameLike = smsFeeLogDTO.getOperatorLike();
            Integer status = smsFeeLogDTO.getStatus();

            opUserNameLike = opUserNameLike != null ? opUserNameLike.trim() : null;

            Integer startTimeF = null;
            Integer endTimeF = null;
            Integer page = smsFeeLogDTO.getPage();
            Integer pageSize = smsFeeLogDTO.getPageSize();
            if (timeSpan != null && timeSpan.size() != 0) {
                startTimeF = DateUtil.getInt(timeSpan.get(0), DateUtil.SDFDate);
                endTimeF = DateUtil.getInt(timeSpan.get(1), DateUtil.SDFDate);
            }

            // 支付状态判断
            if (status != null) {
                FeePayStatusEnum payStatusEnum = FeePayStatusEnum.getByCode(status);
                status = payStatusEnum == null ? null : status;
            }

            page = page != null ? page : 1;
            pageSize = pageSize != null ? pageSize : 15;

            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if(!userModel.isBoss(userEntity)){
                param.put("opUserName", userEntity.getName());
            }
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("corpid", corpid);
            param.put("feeType", PackageTypeEnum.SMS.getType());
            CommentUtil.addToMap(param, "orderIdLike", orderIdLike);
            CommentUtil.addToMap(param, "startTime", startTimeF);
            CommentUtil.addToMap(param, "endTime", endTimeF);
            CommentUtil.addToMap(param, "opUserNameLike", opUserNameLike);
            CommentUtil.addToMap(param, "isPay", status);
            CommentUtil.addToMap(param, "orderByStr", "id desc");


            CommentUtil.addToMap(param, "page", page);

            PageHelper pageHelper = PageHelperUtil.getPageHelper(param, feeLogModel, pageSize);
            List<FeeLogEntity> list = (List<FeeLogEntity>) PageHelperUtil.getEntityList(param, pageHelper, feeLogModel);
            List<SmsFeeLogPojo> resultList = new ArrayList<>();
            if (list != null && list.size() > 0) {
                for (FeeLogEntity entity : list) {

                    String payTimeName = "--";
                    Long payTime = entity.getPayTime();
                    if (payTime != null) {
                        payTimeName = DateUtil.getString(payTime.intValue(), SDFYMDHM);
                    }

                    String statusName = "";
                    FeePayStatusEnum statusEnum = FeePayStatusEnum.getByCode(entity.getIsPay());
                    if (statusEnum != null) {
                        statusName = statusEnum.getName();
                    }

                    SmsFeeLogPojo pojo = new SmsFeeLogPojo();
                    pojo.setFeeLogId(entity.getId());
                    pojo.setFeeName(entity.getFeeName());
                    pojo.setOperator(entity.getOpUserName());
                    pojo.setOutTradeNo(entity.getOrderId());
                    pojo.setPayTime(payTimeName);
                    pojo.setStatusName(statusName);
                    resultList.add(pojo);
                }
            }

            smsFeeLogVO.setPageHelper(pageHelper);
            smsFeeLogVO.setList(resultList);
        } catch (Exception e) {
            LOG.error("获取短信套餐支付记录失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return smsFeeLogVO;
    }

    @Override
    public SmsPayInfoVO getPayInfo(SmsPayInfoDTO smsPayInfoDTO) throws XbbException {
        SmsPayInfoVO smsPayInfoVO = new SmsPayInfoVO();

        String corpid = smsPayInfoDTO.getCorpid();

        CompanyEntity companyEntity = companyModel.getByKey(corpid);
        if (companyEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100011, SmsSetConstant.NOT_COMPANY_INFO);
        }

        FeeEntity feeEntity = feeModel.getByKey(smsPayInfoDTO.getFeeId());
        if(feeEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, SmsSetConstant.SMS_PACKAGE_NOT_EXIST);
        }

        Float totalFee = smsPayInfoDTO.getTotalFee();

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("id", smsPayInfoDTO.getFeeLogId());
        param.put("corpid", corpid);
        param.put("orderId", smsPayInfoDTO.getOutTradeNo());
        List <FeeLogEntity> lists = feeLogModel.findEntitys(param);

        Double totalFeeDouble = Arith.round(totalFee, 2);
        Double realPriceDouble = Arith.round(feeEntity.getRealPrice(), 2);
        int compareFlag = Double.compare(totalFeeDouble, realPriceDouble);

        Boolean isSms = Objects.equals(feeEntity.getType(), PackageTypeEnum.SMS.getType());
        Boolean isEsign = Objects.equals(feeEntity.getType(), PackageTypeEnum.ESIGN.getType());

        LOG.info("totalFeeDouble:" + totalFeeDouble);
        LOG.info("realPriceDouble:" + realPriceDouble);
        LOG.info("isSms:" + isSms);
        LOG.info("isEsign:" + isEsign);

        if(lists.size() == 1 && (isSms || isEsign) && compareFlag == 0){
        //if(lists.size() == 1 && feeEntity.getType().equals(PackageTypeEnum.SMS.getType())){
            FeeLogEntity entity = lists.get(0);
            if(entity.getIsPay().equals(FeePayStatusEnum.WAIT_PAY.getCode())){

//              String info = smsAlipayService.getMobileSMSPayInfo(proBaseConfig.getProjectDingtalkUrl() , entity.getOrderId(), entity.getRealPrice() + "");entity.getRealPrice() + ""
                String info = smsAlipayService.getMobileSMSPayInfo(feeEntity.getType(), proBaseConfig.getPushFrontUrl() , entity.getOrderId(),  entity.getRealPrice() + "", corpid);
                LOG.info("alipay---" + info);
                smsPayInfoVO.setInfo(info);
            }else{
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, SmsSetConstant.QR_CODE_EXPIRED);
            }
        }else{
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, SmsSetConstant.TOTAL_AMOUNT_ERROR);
        }

        return smsPayInfoVO;
    }
}
